#ifndef __SCHEDULER_H__
#define __SCHEDULER_H__

#include <memory>
#include <vector>
#include <list>
#include <functional>

#include "thread.h"
#include "fiber.h"
#include "macro.h"

/******************************************************
* 一个线程调用 Scheduler 调度器 会创建一个线程池 与 调用线程(主线程) 共用任务
* 所有的线程调用run方法, 在run中进行协程的调度
*******************************************************/

namespace sylar
{

// 虚基类: 继续业务框架实现调度，如epoll 的功能
class Scheduler
{
public:
    using ptr = std::shared_ptr<Scheduler>;
    using MutexType = Mutex;

    /// @brief  
    /// @param threads:线程数量
    /// @param use_coller:是否将当前线程也作为调度线程 (加入调度 更好)/ 在线程中调用线程关联器的构造函数时，是否将这个线程纳入线程关联器,不用创建新的线程调用协程
    /// @param  name: 线程调度器的名称
    Scheduler(size_t threads = 1, bool use_coller = true, const std::string& name = "");

    virtual ~Scheduler();

    const std::string& getName() const { return m_name; }

    static Scheduler* GetThis();

    //  主协程 负责线程的调度
    static Fiber* GetMainFiber();

    void start();
    void stop();

    // 调度器执行函数 将协程调度放入队列
    template<typename FiberOrCb>
    void schedule(FiberOrCb fc, int threadId = -1)
    {
        bool need_tickle = false;
        {
            MutexType::Lock lock(m_mutex);
            need_tickle = scheduleNoLock(fc, threadId);
        }
        
        if (need_tickle)
        {
            tickle();
        }
    }

    /// @brief 批量调度协程
    /// @tparam 协程数组的开始 
    /// @param begin 
    /// @param end 
    // template<class InptIterator>
    // void scheduler(InptIterator begin, InptIterator end)
    // {
    //     bool need_tickle = false;
    //     {
    //         MutexType::Lock lock(m_mutex);
    //         while (begin != end)
    //         {   // &*begin  指针去地址 swap
    //             need_tickle = schedulerNoLock(&*begin, -1) || need_tickle;
    //             ++begin;
    //         }
    //     }
    //     if (need_tickle)
    //     {
    //         tickle();
    //     }
    // }
    template<class InputIterator>
    void schedule(InputIterator begin, InputIterator end) {
        bool need_tickle = false;
        {
            MutexType::Lock lock(m_mutex);
            while(begin != end) {
                need_tickle = scheduleNoLock(&*begin, -1) || need_tickle;
                ++begin;
            }
        }
        if(need_tickle) {
            tickle();
        }
    }

protected:
    // 通知协程调度器有任务了
    virtual void tickle();

    // 真正的协程调度
    void run();

    // 停止操作 做一些状态设置？？？？？
    virtual bool stopping();

    size_t getFiberNumber() const { return m_fibers.size(); };
    void setThis();

    bool hasidleThreads() const { return m_idleThreadCount > 0; }

    // 没有任务做时调用 由具体模块实现，比如释放线程 sleep等等
    // 比如网络epoll 时 epoll_wait
    virtual void idle();

private:
    /// @brief 可以执行的参数
    struct ScheduleTask
    {
        /// @brief stl初始化的时候必须要有
        ScheduleTask()
        : threadID(-1)
        {

        }

        ScheduleTask(Fiber::ptr f, int id)
        : fiber(f)
        , threadID(id)
        {
           // SYLAR_ASSERT2(nullptr == f , "nullptr to ScheduleTask");
        }

        /// @brief 
        /// @param f 
        /// @param id 
        ScheduleTask(Fiber::ptr* f, int id)
        : threadID(id)
        {
           // SYLAR_ASSERT2((nullptr == f || nullptr == *f), "nullptr to ScheduleTask");
            fiber.swap(*f); // 引用计数减一
        }

        ScheduleTask(std::function<void()> f, int id)
        : m_cb(f)
        , threadID(id)
        {
            //SYLAR_ASSERT2(nullptr == f , "nullptr to ScheduleTask");
        }

        ScheduleTask(std::function<void()>* f, int id)
        : threadID(id)
        {
           /// SYLAR_ASSERT2((nullptr == f || nullptr == *f), "nullptr to ScheduleTask");
            m_cb.swap(*f);
        }

        // template<class FiberOrCb>
        // ScheduleTask(FiberOrCb , int)
        // {

        // }

        void reset()
        {
            fiber = nullptr;
            m_cb = nullptr;
            threadID = -1;
        }

        Fiber::ptr fiber;
        std::function<void()> m_cb;
        int threadID;
    };
    

private:

    /// @brief 无锁的seceduler
    /// @tparam FiberOrCb 
    /// @param fc 
    /// @param threadId 
    /// @return 需要执行的协程队列是否为空
    // template<class FiberOrCb>
    // bool schedulerNoLock(FiberOrCb fc, int threadId = -1)
    // {
    //     bool need_tickle = m_fibers.empty(); // 是否通知一下
    //     ScheduleTask fb(fc, threadId);
    //     // 这里可以考虑一下 萃取
    //     // if constexpr(std::is_same_v<,>)
    //     if (fb.fiber || fb.m_cb)
    //     {
    //         m_fibers.push_back(fb);
    //     }
    //     // 通知以前时没有任务的 线程陷入内核态（wait）现在放入唤醒一个取出协程
    //     return need_tickle;
    // }
    
    template<class FiberOrCb>
    bool scheduleNoLock(FiberOrCb fc, int thread) {
        bool need_tickle = m_fibers.empty();
        ScheduleTask ft(fc, thread);
        if(ft.fiber || ft.m_cb) {
            m_fibers.push_back(ft);
        }
        return need_tickle;
    }

   

private:

    MutexType m_mutex;
    std::vector<Thread::Ptr> m_threads;
    std::list<ScheduleTask> m_fibers; /// 即将执行 / 计划执行的协程
    std::string m_name;
    Fiber::ptr m_rootFiber;             //主的协程

    

protected:
    std::vector<int> m_theadsId;    // 所有的线程id
    int m_rootThreadId = 0;             // 主线程id use_coller 的线程id
    size_t m_threaadCount = 0;          // 总线程数量
    std::atomic<size_t> m_actiaveThreadCount {0};    // 活跃的线程数量
    std::atomic<size_t> m_idleThreadCount{0};       // 空闲的线程数量

    bool m_stopping = true;                 // 运行状态
    bool m_autoStop = false;                 // 主动停止

};



}

#endif